﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
#if (LINQ)
using System.Linq;
#endif
using System.Text;

using System.ComponentModel;

using Robin.LightNing.Interfaces;
using System.Runtime.Serialization;

namespace Robin.LightNing.Core
{
    /// <summary>
    /// 实体集合抽象基类
    /// </summary>
    [Serializable]
#if (!WindowsCE)
    [CollectionDataContract]
#endif
    abstract public class rbEntityCollectionBase : IEntityCollection, IEnumerable, IComponent
    {
        #region IComponent Members

        public event EventHandler Disposed;

        ISite IComponent.Site
        {
            get { return site; }
            set { site = value; }
        }
        [NonSerialized]
        private ISite site = null;

        #endregion

        #region IDisposable Members

        /// <summary>
        /// <see cref="IDisposable"/>.
        /// </summary>
        public void Dispose()
        {
            if (site != null && site.Container != null)
            {
                site.Container.Remove(this);
            }

            if (Disposed != null)
            {
                Disposed.Invoke(this, System.EventArgs.Empty);
            }
        }

        #endregion		

        #region Virtual Methods

        virtual protected rbEntity CreateEntity()
        {
            return null;
        }

        virtual internal IList GetList()
        {
            return null;
        }

        virtual internal IEnumerable GetDeletedEntities()
        {
            return null;
        }

        virtual internal IEnumerable GetEntities()
        {
            return null;
        }

        virtual internal PropertyDescriptorCollection GetProperties(rbEntity entity, rbEntityCollectionBase baseCollection)
        {
            return null;
        }

        virtual internal void AddEntityToDeletedList(rbEntity entity)
        {

        }

        virtual internal void ClearDeletedEntries()
        {

        }

        virtual internal void OnUpdateViewNotification(object sender, ListChangedType changeType, rbEntity obj)
        {

        }

        virtual protected rbDynamicQuery GetDynamicQuery()
        {
            return null;
        }

        virtual protected void HookupQuery(rbDynamicQuery query)
        {

        }

        virtual protected IMetadata Meta
        {
            get
            {
                return null;
            }
        }

        virtual public void Save()
        {

        }

        virtual public void Save(bool continueUpdateOnError)
        {

        }

        virtual protected string GetCollectionName()
        {
            return "";
        }

        /// <summary>
        /// 当Entity需要连接的时候调用. 
        /// </summary>
        /// <returns></returns>
        virtual protected string GetConnectionName()
        {
            return null;
        }

        /// <summary>
        /// 生成的类重写用于支持动态查询的预获取逻辑.
        /// </summary>
        /// <param name="row">用于创建实体的行</param>
        /// <param name="ordinals">列号,如果为null，创建并返回</param>
        /// <returns>列位置</returns>
        virtual protected Dictionary<string, int> PopulateCollectionPrefetch(DataRow row, Dictionary<string, int> ordinals)
        {
            return null;
        }
        /// <summary>
        /// 
        /// </summary>
        virtual public void AcceptChanges()
        {

        }
        /// <summary>
        /// 
        /// </summary>
        virtual public void RejectChanges()
        {

        }
        /// <summary>
        /// 
        /// </summary>
        virtual public int Count
        {
            get
            {
                return 0;
            }
        }
        /// <summary>
        /// 
        /// </summary>
        virtual public bool IsDirty
        {
            get
            {
                return false;
            }
        }
        /// <summary>
        /// 
        /// </summary>
        virtual public bool IsGraphDirty
        {
            get
            {
                return false;
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public virtual bool LoadAll()
        {
            return false;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sqlAccessType"></param>
        /// <returns></returns>
        public virtual bool LoadAll(rbSqlAccessType sqlAccessType)
        {
            return false;
        }
        /// <summary>
        /// 
        /// </summary>
        virtual public void MarkAllAsDeleted()
        {

        }
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        virtual public Type GetEntityType()
        {
            return null;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="entity"></param>
        internal virtual void RemoveEntity(rbEntity entity)
        {

        }
        /// <summary>
        /// 
        /// </summary>
        virtual public void CombineDeletedEntities()
        {

        }
        /// <summary>
        /// 
        /// </summary>
        virtual public void SeparateDeletedEntities()
        {

        }



        #endregion

        /// <summary>
        /// IEntityCollection接口半隐藏RobinLightNing请求的基础类属性.
        /// </summary>
        public IEntityCollection rb
        {
            get { return this as IEntityCollection; }
        }


        private rbProviderSpecificMetadata GetProviderMetadata()
        {
            // We're on our own, use our own rbProviderSpecificMetadata
            string key = this.rb.Connection.ProviderMetadataKey;
            return this.Meta.GetProviderMetadata(key);
        }


        [NonSerialized]
        private rbConnection connection;

        #region IEntityCollection Members

        rbConnection IEntityCollection.Connection
        {
            get
            {
                if (this.connection == null)
                {
                    this.connection = new rbConnection();

                    if (rbConnection.ConnectionService != null)
                    {
                        this.connection.Name = rbConnection.ConnectionService.GetName();
                    }
                    else
                    {
                        string connName = this.GetConnectionName();
                        if (connName != null)
                        {
                            this.connection.Name = connName;
                        }
                    }
                }

                return this.connection;
            }
            set { this.connection = value; }
        }

        string IEntityCollection.Catalog
        {
            get
            {
                if (this.rb.Connection.Catalog != null)
                    return this.rb.Connection.Catalog;
                else
                    return this.GetProviderMetadata().Catalog;
            }
        }

        string IEntityCollection.Schema
        {
            get
            {
                if (this.rb.Connection.Schema != null)
                    return this.rb.Connection.Schema;
                else
                    return this.GetProviderMetadata().Schema;
            }
        }

        string IEntityCollection.Destination
        {
            get { return this.GetProviderMetadata().Destination; }
        }

        string IEntityCollection.Source
        {
            get { return this.GetProviderMetadata().Source; }
        }

        string IEntityCollection.spInsert
        {
            get { return this.GetProviderMetadata().spInsert; }
        }

        string IEntityCollection.spUpdate
        {
            get { return this.GetProviderMetadata().spUpdate; }
        }

        string IEntityCollection.spDelete
        {
            get { return this.GetProviderMetadata().spDelete; }
        }

        string IEntityCollection.spLoadAll
        {
            get { return this.GetProviderMetadata().spLoadAll; }
        }

        string IEntityCollection.spLoadByPrimaryKey
        {
            get { return this.GetProviderMetadata().spLoadByPrimaryKey; }
        }

        rbDynamicQuery IEntityCollection.Query
        {
            get { return this.GetDynamicQuery(); }
        }

        void IEntityCollection.HookupQuery(rbDynamicQuery query)
        {
            this.HookupQuery(query);
        }

        IEnumerable IEntityCollection.DeletedEntities
        {
            get { return GetDeletedEntities(); }
        }

        IMetadata IEntityCollection.Meta
        {
            get { return this.Meta; }
        }

        bool IEntityCollection.IsLazyLoadDisabled
        {
            get { return this._isLazyLoadDisabled; }
            set { this._isLazyLoadDisabled = value; }
        }

        Dictionary<string, int> IEntityCollection.PopulateCollection(DataRow row, Dictionary<string, int> ordinals)
        {
            return this.PopulateCollectionPrefetch(row, ordinals);
        }

        #endregion

        #region IEnumerable Members

        IEnumerator IEnumerable.GetEnumerator()
        {
            return this.GetEntities().GetEnumerator();
        }

        #endregion

        /// <summary>
        /// 该方法只对Windows.Forms应用程序有效
        /// </summary>
        public bool EnableHierarchicalBinding
        {
            get
            {
                return this.enableHierarchcialBinding;
            }

            set
            {
                if (this.enableHierarchcialBinding != value)
                {
                    if (this.m_bindingPropertyCache != null)
                    {
                        this.m_bindingPropertyCache.Clear();
                    }
                    this.enableHierarchcialBinding = value;
                }
            }
        }

        protected Dictionary<Type, PropertyDescriptorCollection> BindingPropertyCache
        {
            get
            {
                if (this.m_bindingPropertyCache == null)
                {
                    this.m_bindingPropertyCache = new Dictionary<Type, PropertyDescriptorCollection>();
                }

                return this.m_bindingPropertyCache;
            }
        }

        [NonSerialized]
        internal bool isSorted;

        [NonSerialized]
        internal PropertyDescriptor sortProperty;

        [NonSerialized]
        internal ListSortDirection sortDirection = ListSortDirection.Ascending;

        [NonSerialized]
        private Dictionary<Type, PropertyDescriptorCollection> m_bindingPropertyCache;

        [NonSerialized]
        private bool enableHierarchcialBinding = true;

        [NonSerialized]
        internal Dictionary<string, int> selectedColumns;

        [NonSerialized]
        internal Dictionary<string, rbColumnMetadata> extraColumnMetadata;

        [NonSerialized]
        internal bool _isLazyLoadDisabled;
    }
}
